package com.tcfvic.server.upload;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;

import com.tcfvic.client.PersonService;
import com.tcfvic.client.pojos.Rto;
import com.tcfvic.server.PersonServiceImpl;

public class RTOUpload extends HttpServlet implements IExcelFormat {
	private static final long serialVersionUID = 5567237221724423872L;

	private static final Logger logger = Logger.getLogger(RTOUpload.class);

	private List<String> errorList = new ArrayList<String>();
	private int numberImported = 0;

	private Map<Integer, Rto> rtos;
	private PersonService personService = new PersonServiceImpl();

	public RTOUpload() {
		logger.info("Uploading RTO details.");
		personService = new PersonServiceImpl();
		initialise();
	}

	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/plain");
		logger.info("Inside RTO File Upload Servlet...............>>>>>>>>>>");
		personService = new PersonServiceImpl();
		initialise();
		try {
			getFileItem(request);
		} catch (Exception e) {
			logger.error(e);
		}
	}

	@SuppressWarnings("unchecked")
	private FileItem getFileItem(final HttpServletRequest request) {
		FileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload upload = new ServletFileUpload(factory);
		// Create a progress listener, if want to use
		ProgressListener progressListener = new ProgressListener() {
			private long megaBytes = -1;
			int i = -1;

			public void update(long pBytesRead, long pContentLength, int pItems) {
				if (i != pItems) {
					i = pItems;
				}
				long mBytes = pBytesRead / 10000;
				if (megaBytes == mBytes) {
					return;
				}
				megaBytes = mBytes;
			}
		};
		upload.setProgressListener(progressListener);

		try {
			List items = upload.parseRequest(request);
			Iterator it = items.iterator();
			while (it.hasNext()) {
				FileItem item = (FileItem) it.next();
				if (!item.isFormField()) {
					this.processUpload(item);
				}
			}
		} catch (Exception e) {
			logger.error(e);
			return null;
		}
		return null;
	}

	private void processUpload(FileItem uploadItem) {
		try {
			String uploadDir = getServletContext().getRealPath("/")
					+ "tcfuaUplaod/";
			File file = new File(uploadDir);
			file.mkdirs();

			InputStream is = uploadItem.getInputStream();
			String filename = String.valueOf(System.currentTimeMillis())
					+ ".xls";
			File uploadedFile = new File(uploadDir + "/" + filename);
			DataOutputStream out = null;
			out = new DataOutputStream(new BufferedOutputStream(
					new FileOutputStream(uploadedFile)));
			while (true) {
				int value = is.read();
				out.write(value);
				if (value < 0) {
					break;
				}
			}
			out.close();
			uploadFile(uploadedFile);

		} catch (IOException e) {
			logger.error(e);
		}
	}

	public void initialise() {
		List<Rto> rtoResultList = personService.getAllRTOs();
		rtos = new HashMap<Integer, Rto>();
		for (Rto rto : rtoResultList) {
			rtos.put(rto.getId(), rto);
		}
	}

	public static void main(String... args) {
		RTOUpload f = new RTOUpload();
		f.uploadFile(new File("c:/temp/FINAL - RTO (1).xls"));
	}

	public void uploadFile(File file) {
		logger.info("In ExmpStatusUpload.uploadFile");

		try {
			Workbook workbook = createWorkbook(file);
			if (workbook.getSheets() != null) {
				processSheets(workbook);
			}
		} catch (Exception e) {
			logger.error(e);
		}
	}

	public void processSheets(Workbook workbook) throws Exception {
		Sheet sheet = workbook.getSheet(0);
		int i = 1;
		while (true) {
			i++;
			if (sheet.getCell("A" + i) != null
					&& !sheet.getCell("A" + i).getContents().isEmpty()) {
				try {
					Rto rto = getRTONameIfExists(sheet.getRow(i - 1));
					// if (rtoNameAlreadyInDatabase != null) {
					// continue;
					// }

					processRto(rto, sheet.getRow(i - 1));
					numberImported++;
				} catch (Exception e) {
					logger
							.error(
									"An error occured processing employment status ",
									e);
				}
			} else {
				break;
			}
		}
	}

	private void processRto(Rto rto, Cell[] row) throws Exception {
		int colCount = -1;

		String name = null;
		String campus = null;
		String street = null;
		String suburb = null;
		String state = null;
		String postcode = null;
		String rtoPhone = null;
		String rtoFax = null;
		String website = null;
		String contact = null;
		String position = null;
		String contactPhone = null;
		String contactMobile = null;
		String contactEmail = null;
		String notes = null;

		try {
			name = getStringFromCell(row, ++colCount);
			if (name.equals("TAFE Illawarra - Shellharbour")) {
				System.out.println("fdsa");
			}
			campus = getStringFromCell(row, ++colCount);
			street = getStringFromCell(row, ++colCount);
			suburb = getStringFromCell(row, ++colCount);
			state = getStringFromCell(row, ++colCount);
			postcode = getStringFromCell(row, ++colCount);
			rtoPhone = getStringFromCell(row, ++colCount);
			rtoFax = getStringFromCell(row, ++colCount);
			website = getStringFromCell(row, ++colCount);
			contact = getStringFromCell(row, ++colCount);
			position = getStringFromCell(row, ++colCount);
			contactPhone = getStringFromCell(row, ++colCount);
			contactMobile = getStringFromCell(row, ++colCount);
			contactEmail = getStringFromCell(row, ++colCount);
			notes = getStringFromCell(row, ++colCount);

			logger.info("Importing " + name);
			if (rto == null) {
				rto = new Rto();
			}
			rto.setName(name);
			rto.setCampus(campus);
			rto.setStreet1(street);
			rto.setSuburb(suburb);
			rto.setState(state);
			rto.setPostcode(postcode);
			rto.setRtoPhone(rtoPhone);
			rto.setRtoFax(rtoFax);
			rto.setWebsite(website);
			rto.setContactName(contact);
			rto.setContactPosition(position);
			rto.setTel1(contactPhone);
			rto.setTel2(contactMobile);
			rto.setEmail(contactEmail);
			rto.setNotes(notes);
			personService.saveRTO(rto);
			logger.info("Successfully imported " + name);
		} catch (Exception e) {
			logger.warn("Error getting row data for rto upload", e);
		}

	}

	private String getStringFromCell(Cell[] row, int col) {
		try {
			return row[col].getContents().trim();
		} catch (Exception e) {
			return "";
		}
	}

	private Rto getRTONameIfExists(Cell[] row) {
//		String rtoName = fullCamelCase(row[0].getContents());
//		String rtoCampus = fullCamelCase(row[1].getContents());
		String rtoName = row[0].getContents();
		String rtoCampus = row[1].getContents();
		System.out.println(rtoName);
		if (row[0].getContents().equals("TAFE Illawarra - Shellharbour")) {
			System.out.println(rtoName);
		}

		for (Rto rto : rtos.values()) {
			if (rto.getName().equals(rtoName)
					&& rto.getCampus().equals(rtoCampus)) {
				return rto;
			}
		}
		String msg = "Rto not found in database: " + rtoName;
		errorList.add(msg);
		logger.warn(msg);

		return null;
	}

	private String fullCamelCase(String camelMe) {
		StringBuffer sb = new StringBuffer();
		String[] words = camelMe.split("\\s");
		for (String s : words) {
			sb.append(capitalize(s));
		}
		return sb.toString();
	}

	private static String capitalize(String s) {
		if (s.length() == 0)
			return s;
		return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
	}

	public Workbook createWorkbook(File file) throws BiffException, IOException {
		return Workbook.getWorkbook(file);
	}

}
